<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Generator函数</title>
</head>
<body>
<!--
 Generator函数
  概念：
    1、ES6 提供的解决异步编程的方案之一
    2、Generator 函数是一个状态机，内部封装了不同状态的数据，
    3、用来生成遍历器对象
    4、可暂停函数(惰性求值), yield 可暂停，next 方法可启动。每次返回的是 yield 后的表达式结果
  特点：
    1、function 与函数名之间有一个星号
    2、内部用 yield 表达式来定义不同的状态
    例如：
      function* generatorExample(){
        let result = yield 'hello';  // 状态值为 hello
        yield 'generator'; // 状态值为 generator
      }
    3、generator 函数返回的是指针对象(接 11 章节里 iterator)，而不会执行函数内部逻辑
    4、调用 next 方法函数内部逻辑开始执行，遇到 yield 表达式停止，返回 {value: yield 后的表达式结果 /undefined, done: false/true}
    5、再次调用 next 方法会从上一次停止时的 yield 处开始，直到最后
    6、yield 语句返回结果通常为 undefined， 当调用 next 方法时传参内容会作为启动时 yield 语句的返回值。
-->
<script src="./js/jquery-1.10.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
  // 小试牛刀
  function* generatorTest() {
    console.log('函数开始执行');
    yield 'hello';
    console.log('函数暂停后再次启动');
    yield 'generator';
  }

  // 生成遍历器对象
  let Gt = generatorTest();
  // 执行函数，遇到 yield 后即暂停
  console.log(Gt); // 遍历器对象
  let result = Gt.next(); // 函数执行,遇到 yield 暂停
  console.log(result); // {value: "hello", done: false}
  result = Gt.next(); // 函数再次启动
  console.log(result); // {value: 'generator', done: false}
  result = Gt.next();
  console.log(result); // {value: undefined, done: true} 表示函数内部状态已经遍历完毕

  // 对象的 Symbol.iterator 属性;
  let myIterable = {};
  myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 4;
  };
  for (let i of myIterable) {
    console.log(i);
  }
  let obj = [...myIterable];
  console.log(obj);

  console.log('-------------------------------');
  // 案例练习
  /*
  * 需求：
  * 1、发送ajax请求获取新闻内容
  * 2、新闻内容获取成功后再次发送请求，获取对应的新闻评论内容
  * 3、新闻内容获取失败则不需要再次发送请求。
  *
  * */
  function* sendXml() {
    // url为next传参进来的数据
    let url = yield getNews('http://localhost:3000/news?newsId=2');
    yield getNews(url);
  }

  function getNews(url) {
    $.get(url, function (data) {
      console.log(data);
      let commentsUrl = data.commentsUrl;
      let url = 'http://localhost:3000' + commentsUrl;
      // 当获取新闻内容成功，发送请求获取对应的评论内容
      // 调用next传参会作为上次暂停是yield的返回值
      sx.next(url);
    })
  }


  let sx = sendXml();
  // 发送请求获取新闻内容
  sx.next();
</script>
</body>
</html>
